-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow subclasses to use _fromObject. #5917
Conversation
This change would be good for me, but how would we solve full canvas restoration? we have still this utility here that is a big part of the process
How do you suggest we come back from a full string representation? |
maybe with the use of namespace and adding a namespace property in objects exports it can work, assuming that in 2020 using window and global is still fine for developers. Let me know if you want to push this forward and if you need some help. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
c5a5e38
to
03c469f
Compare
Good point! I extended the JSFiddle to contain import/export: https://jsfiddle.net/Harmageddon/qwbo6053/ |
i ll get back to this, i m currently a bit busy |
Ok, no problem! |
i would be very interested in this feature too. Using angular with fabricjs, i dont seem to be able to create custom compontents that can be deserialized (fabric cant find them). |
you can deserialize back if you add them to fabric namespace following the lowerCase schema. if the class is CustomRect the type has to be set to 'customRect' |
03c469f
to
7f7827e
Compare
@Harmageddon i see you have changed approach a bit. I would be fine with this change if you can care to document with an example. Does not seem that the default is changed. |
well broken UTs apart. |
What about making a rule? object.type can be |
Yes, as mentioned above, because it seems to be a cleaner solution, and because
That's because of the toObject method being changed, as I mentioned here:
So either we add the namespace property to the expected value in the unit tests (if we want the namespace property to be exported always), or we just don't export it in
That's also possible, would just need to change For my use case, I provided an example with the fiddle at https://jsfiddle.net/Harmageddon/qwbo6053/, but would be happy to provide more documentation if wanted. |
i think if we export the namespace only when is different from falsy and we make test pass, plus we add a test with a custom namespace, we are good to go. |
I modified the |
you can try to swap window with document.defaultView, that should help to pass |
caf2696
to
f30c782
Compare
Somehow I got Github to hiccup by altering the commit history here. I can create a new PR or maybe it can be solved when merging by squashing. |
merge + squash should do it. |
so i see there is will to solve here. i do not want to have this stopped forever. |
Thank you! I have enabled "Allow edits from maintainers." for this PR. |
diff --git a/src/util/misc.js b/src/util/misc.js
index 969aff64..7856dcd0 100644
--- a/src/util/misc.js
+++ b/src/util/misc.js
@@ -1,4 +1,4 @@
-(function(global) {
+(function() {
var sqrt = Math.sqrt,
atan2 = Math.atan2,
@@ -318,7 +318,7 @@
var parts = namespace.split('.'),
len = parts.length, i,
- obj = global || fabric.window;
+ obj = typeof global === 'undefined' ? fabric.window : global;
for (i = 0; i < len; ++i) {
obj = obj[parts[i]];
@@ -975,4 +975,4 @@
}).join(' ') + ')';
}
};
-})(typeof exports !== 'undefined' ? exports : this);
+})();
diff --git a/test/unit/object.js b/test/unit/object.js
index dff18a80..c018aa58 100644
--- a/test/unit/object.js
+++ b/test/unit/object.js
@@ -1,4 +1,4 @@
-(function(){
+(function(global){
var canvas = this.canvas = new fabric.StaticCanvas(null, {enableRetinaScaling: false});
@@ -464,21 +464,21 @@
});
QUnit.test('clone with namespace', function(assert) {
- var glob = fabric.isLikelyNode ? global : window;
-
- glob.Custom = {
- Object: fabric.util.createClass(fabric.Object, {
- 'namespace': 'Custom',
- })
+ var MyClass = fabric.util.createClass(fabric.Object, {
+ namespace: 'MyNameSpace',
+ type: 'myClass'
+ });
+ MyClass.fromObject = function(object, callback) {
+ return fabric.Object._fromObject('MyClass', object, callback);
};
-
- var cObj = new glob.Custom.Object();
-
+ global.MyNameSpace = {
+ MyClass: MyClass
+ };
+ var cObj = new MyClass();
assert.ok(typeof cObj.clone === 'function');
cObj.clone(function(clone) {
- assert.ok(clone instanceof glob.Custom.Object);
-
- delete glob.Custom;
+ assert.ok(clone instanceof MyClass);
+ delete global.MyNameSpace;
});
});
@@ -1289,4 +1289,4 @@
object.fill = 'transparent';
assert.equal(object.hasFill(), false, 'with a color that is transparent, hasFill is true');
});
-})();
+})(typeof global !== 'undefined' ? global : this); |
i can't push, unsure what is wrong, that is what i did, could you please merge it in your branch and let's move forward from there. |
Co-authored-by: Andrea Bogazzi <andreabogazzi79@gmail.com>
Awesome, it works! Thank you! |
This discussion should be revived coming into v6. |
I prefer some kind of global registry/map of classes that fabric holds. fabric.registerClass(type /** id */, clazz) and/or perhaps another option for overriding while loading from JSON? and/or have a resolver that the dev can completely override: fabric.resolveClass = function(type) {
// return a class constructor
} |
The default
fromObject
methods for fabric objects usefabric.Object._fromObject
. This works for subclasses, too, if you define thefromObject
method like this:However, this works only for subclasses within the
fabric
"namespace". For other namespaces,_fromObject
fails to resolve the correct constructor, which means you would have to write your ownfromObject
method if you have subclasses in other namespaces.Demo
See the demo: http://jsfiddle.net/5xaq1rz6/5/
Here, we have three kinds of rectangles. The blue one is a normal
fabric.Rect
, while the other two are instances of subclasses. To make the difference visible, the subclasses only allow their instances to be moved horizontally.The red rectangle is an instance of
fabric.CustomRect
, so within thefabric
namespace. Clone it by selecting it and clicking the clone button, and you'll see that a new instance of the same subclass is generated correctly.The green rectangle is an instance of
Custom.Rect
, a subclass in a different namespace. Clone it, and you'll see that the new instance is a normal rectangle instead of the subclassed one, because the definition forfromObject
holds:So the constructor used for the new object will be
fabric.Rect
.Proposed changes
With this change, instead of strings defining the class names, classes themselves can be passed as a
className
parameter. The code for our rectangle subclass would now be:and the object can be reconstructed correctly. For all classes inside the
fabric
namespace, nothing changes in the usage offromObject
.